
#include <cstdio>
#include <BCharEvent>
#include <BKeyEvent>
#include <BEvent>
#include <BEvent>
#include <BFocusEvent>
#include <BMouseEvent>
#include <BEvent>
#include <BCharEvent>
#include <BDragEvent>
#include <BTextEdit>
#include <BPainter>
#include <BCursor>
#include <BDrag>
#include <BSystem>
#include <BScreen>
#include "IWindow.h"
#include "member_BWidget.h"

using namespace BWE;

extern BList<IWindowHolder> app_windows;

#ifdef _LINUX_

bool IWindow::create()
{
	screen = 0;
	display = 0;
	context = 0;
	style = 0;

	display = XOpenDisplay(0);
	screen = XScreenOfDisplay(display, DefaultScreen(display));

	const char* title = boss->title().cstr();

	BRect rect = boss->rect();
	int x = rect.x();
	int y = rect.y();
	int w = rect.width();
	int h = rect.height();

	int attribList[]  = {GLX_RGBA, GLX_DOUBLEBUFFER, None};
  	XVisualInfo* vi = glXChooseVisual(display, 0, attribList);
  	if (vi == 0)
  	{
  		XCloseDisplay(display);
  		display = 0;
    	perror("NO RGBA visual with double buffer");
    	return false;
  	}
 
  	context = glXCreateContext(display, vi, None, GL_TRUE);
  	if (context == 0)
  	{
  		XCloseDisplay(display);
  		display = 0;
    	perror("could not create rendering context");
    	return false;
    }
	
 	Window root = RootWindow(display, 0);
	
	unsigned int type = InputOutput;
  	unsigned long mask = CWBorderPixel | CWColormap | CWEventMask;
 	int depth = vi->depth;//DefaultDepth(display, 0);
  	Visual* visual = vi->visual;//DefaultVisual(display, 0);
	
 	XSetWindowAttributes attribs;
 	attribs.colormap = XCreateColormap(display, root, vi->visual, AllocNone);
  	attribs.border_pixel = 50;
  	attribs.event_mask = CreateNotify\
  						 | ExposureMask\
  						 | FocusChangeMask\
  						 | KeyPressMask\
  						 | KeyReleaseMask\
  						 | PointerMotionMask\
  						 | ButtonPressMask\
  						 | ButtonReleaseMask\
  						 | ButtonMotionMask\
  						 | EnterWindowMask\
  						 | LeaveWindowMask\
  						 | StructureNotifyMask;

  	hwnd = XCreateWindow(display, root, x, y, w, h, 0, depth, type, visual, mask, &attribs);
	if(boss->visible())
		XMapWindow(display, hwnd);
	return true;
}
bool IWindow::destroy()
{
	if (context)
		glXDestroyContext(display, context);
	if (hwnd)
		XDestroyWindow(display, hwnd);
	if (display)
		XCloseDisplay(display);
	display = 0;
	hwnd = 0;
	context = 0;
	return true;
}
bool IWindow::makeCurrent(bool yes)
{
	if (yes)
		glXMakeCurrent(display, hwnd, context);
	else
		glXMakeCurrent(display, 0, 0);
}
bool IWindow::swapBuffers()
{
	glXSwapBuffers(display, hwnd);
	return true;
}

void IWindow::setWindowPos(const BPoint& pos)
{
	if(hwnd)
	{
		if(pos != boss->pos())
		{
			XMoveWindow(display, hwnd, pos.x(), pos.y());
		}
	}
}
BPoint IWindow::getWindowPos()
{
	return boss->pos();
}

void IWindow::setWindowSize(const BSize& size)
{
	if (boss->size() != size)
	{
		XResizeWindow(display, hwnd, size.width(), size.height());
	}
}
BSize IWindow::getWindowSize()
{
	return boss->size();
}

void IWindow::showNormal()
{

}
void IWindow::showMaxinum()
{

}
void IWindow::showMininum()
{
}
void IWindow::showFullScreen()
{

}
void IWindow::hideWindow()
{

}

void IWindow::freshCursor()
{
	
}
Button filterButton(unsigned int button)
{
	if(button == Button1)
		return Button_Left;
	if(button == Button2)
		return Button_Middle;
	if(button == Button3)
		return Button_Right;
	return Button_None;
}

bool IWindow::procEvent(const XEvent& event)
{
	switch(event.type)
	{
	case CreateNotify:
	{
		const XCreateWindowEvent& createEvent = (const XCreateWindowEvent&)event;
		boss->setPos(createEvent.x, createEvent.y);
		boss->setSize(createEvent.width, createEvent.height);
		break;
	}
	case DestroyNotify:
	{
		const XDestroyWindowEvent& destroyEvent = (const XDestroyWindowEvent&)event;
		break;
	}
	case Expose:
	{
		refresh = true;
		const XExposeEvent& exposeEvent = (const XExposeEvent&)event;
		break;
	}
	case ConfigureNotify:
	{
		const XConfigureEvent& configEvent = (const XConfigureEvent&)event;
		boss->setPos(configEvent.x, configEvent.y);
		boss->setSize(configEvent.width, configEvent.height);
		break;
	}
	case FocusIn:
	{
		focusing = true;
		this->focus(boss);
		break;
	}
	case FocusOut:
	{
		focusing = false;
		this->focus(0);
		break;
	}
	case KeyPress:
	{
		const XKeyEvent& pressEvent = (const XKeyEvent&)event;
		BKeyEvent keyEvent(Event_KeyUp);
		break;
	}
	case KeyRelease:
	{
		const XKeyEvent& pressEvent = (const XKeyEvent&)event;
		BKeyEvent keyEvent(Event_KeyDown);;
		break;
	}
	case EnterNotify:
	{
		BMouseEvent mouseEvent(Event_MouseEnter);
		widget_member(boss)->procEvent(mouseEvent);
		break;
	}
	case LeaveNotify:
	{
		BMouseEvent mouseEvent(Event_MouseLeave);
		widget_member(boss)->procEvent(mouseEvent);
		break;
	}
	case ButtonPress:
	{
		const XButtonEvent& buttonEvent = (const XButtonEvent&)event;
		BPoint absolutePos(buttonEvent.x, buttonEvent.y);
		BPoint globalPos(buttonEvent.x_root, buttonEvent.y_root);
		Button button = filterButton(buttonEvent.button);
		
		BMouseEvent mouseEvent(Event_MousePress, button);
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setGlobalPos(globalPos);
		this->procMousePress(mouseEvent);
		break;
	}
	case ButtonRelease:
	{
		const XButtonEvent& buttonEvent = (const XButtonEvent&)event;
		BPoint absolutePos(buttonEvent.x, buttonEvent.y);
		BPoint globalPos(buttonEvent.x_root, buttonEvent.y_root);
		Button button = filterButton(buttonEvent.button);
		
		BMouseEvent mouseEvent(Event_MouseRelease, button);
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setGlobalPos(globalPos);
		this->procMouseRelease(mouseEvent);
		break;
	}
	case MotionNotify:
	{
		const XMotionEvent& motionEvent = (const XMotionEvent&)event;
		BPoint absolutePos(motionEvent.x, motionEvent.y);
		BPoint globalPos(motionEvent.x_root, motionEvent.y_root);
		
		BMouseEvent mouseEvent(Event_MouseMove);
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setGlobalPos(globalPos);
		this->procMouseMove(mouseEvent);
		break;
	}
	case MapNotify:
	{
		const XMapEvent& mapEvent = (const XMapEvent&)event;
		break;
	}
	case UnmapNotify:
	{
		const XUnmapEvent& unmapEvent = (const XUnmapEvent&)event;
		break;
	}
	default:
		break;
	}
	return true;
}
#endif
